using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using GameFramework.Localization;
using LS.Editor.Tool;
using LS.UnityExtensions.Editor;
using LS.Localization;
using Type = System.Type;

namespace LS.Editor
{
    public sealed class LocalizationConfigEditorWindow : EditorWindow
    {
        private static readonly string s_LocalizationSettingSearchFilter = "t:LS.Localization.LocalizationSetting";

        //[MenuItem("Lancer Studio/Localization Window")]
        public static void OpenLocalizationConfigWindow()
        {
            GetWindow<LocalizationConfigEditorWindow>("Localization").Focus();
        }
        private static readonly Type s_LanguageSettingType = typeof(LanguageSetting);
        private static readonly Type s_TextAssetType = typeof(LanguageSetting);

        private Vector2 m_ScrollValue = Vector2.zero;
        private HashSet<string> m_TextKeysSet;
        private List<string> m_TextKeys;
        private List<Language> m_ActivedLanguages;
        private Dictionary<Language, List<TextAsset>> m_LanguageAssetCollection;
        private Dictionary<Language, LanguageSettingTableItem> m_LanguageSettingTableItemMap;
        private Dictionary<int, LanguageSettingTableItem> m_LanguageSettingIdMap;
        private Dictionary<TextAsset, XMLTextFileTableItem> m_XmlAssetTableItemMap;

        private LocalizationSetting m_Localization;
        private TableView m_TableView;

        private float m_BottomBarHeight = 30;
        private TableColumn[] m_BasisColumn = new TableColumn[]
        {
            new LabelColumn(),
            new ObjectReferenceColumn(),
        };

        internal bool Avaliable
        {
            get => m_Localization != null;
        }

        class Contents
        {
            public readonly static GUIContent KeysTitle = new GUIContent("Language Referense");

        }

        class Styles
        {
            public readonly static GUILayoutOption HeaderHeight = GUILayout.Height(30);
            public readonly static GUILayoutOption HeaderWidth = GUILayout.Width(150);
            public readonly static GUILayoutOption FirstColumnWidth = GUILayout.Width(200);
            public readonly static GUILayoutOption ContentColumnWidth = GUILayout.Width(150);

            public readonly static GUILayoutOption HorizontalSplitLineWidth = GUILayout.Width(1);
            public readonly static GUILayoutOption VerticalSplitLineHeigth = GUILayout.Height(1);
        }

        private void OnEnable()
        {
            m_TextKeysSet = new HashSet<string>();
            m_TextKeys = new List<string>();
            m_ActivedLanguages = new List<Language>();
            m_XmlAssetTableItemMap = new Dictionary<TextAsset, XMLTextFileTableItem>();
            m_LanguageAssetCollection = new Dictionary<Language, List<TextAsset>>();
            m_LanguageSettingTableItemMap = new Dictionary<Language, LanguageSettingTableItem>();
            m_LanguageSettingIdMap = new Dictionary<int, LanguageSettingTableItem>();

            ResearchLocalizationSetting();
            InitTableView();
        }

        private void OnDisable()
        {

        }

        private void OnGUI()
        {
            if (!Avaliable)
            {
                DrawCreateButton();
            }
            else
            {
                DrawLocalizationSettingView();
            }
        }

        private void InitTableView()
        {
            m_TableView = new TableView(m_BasisColumn);
            List<TableColumn> list = new List<TableColumn>();
            CreateTableViewColumn(list);
            m_TableView.AddColumn(list.ToArray());
            m_TableView.AddItem(m_LanguageSettingTableItemMap.Values.ToArray());
            m_TableView.Reload();
        }

        private void DrawCreateButton()
        {
            if (GUILayout.Button("Create Localization Setting"))
            {
                string path = EditorUtility.OpenFolderPanel("Select Folder", $"{Application.dataPath}/Assets", "Localization");
                Debug.Log($"Select folder: {path}");
                if (!path.StartsWith(Application.dataPath))
                {
                    Debug.LogError("You must select a folder within this project!");
                    return;
                }

                if (!string.IsNullOrEmpty(path))
                {
                    var ls = LocalizationSettingUtil.CreateOrGetLocalizationSetting($"{path}/LocalizationSetting.asset");
                    SetupLocalizationSettingEditor(ls);
                }
            }
        }

        private void DrawLocalizationSettingView()
        {
            Rect rect = new Rect(5, 5, position.width - 10, position.height - 10 - m_BottomBarHeight);
            m_TableView?.OnGUI(rect);
        }

        private void DrawHorizontalSplitLine(float heigth, float yOffset = 0)
        {
            Rect rect = EditorGUILayout.GetControlRect(GUILayout.Height(heigth), Styles.HorizontalSplitLineWidth);
            rect.y += yOffset;
            EditorGUI.DrawRect(rect, LSEditorStyle.Line);
        }

        private void DrawHorizontalSplitLine(GUILayoutOption heigth, float yOffset = 0)
        {
            Rect rect = EditorGUILayout.GetControlRect(heigth, Styles.HorizontalSplitLineWidth);
            rect.y += yOffset;
            EditorGUI.DrawRect(rect, LSEditorStyle.Line);
        }

        private void DrawVerticalSplitLine(float width, float xOffset = 0)
        {
            Rect rect = EditorGUILayout.GetControlRect(GUILayout.Width(width), Styles.VerticalSplitLineHeigth);
            rect.x += xOffset;
            EditorGUI.DrawRect(rect, LSEditorStyle.Line);
        }

        private void DrawVerticalSplitLine(GUILayoutOption width, float xOffset = 0)
        {
            Rect rect = EditorGUILayout.GetControlRect(width, Styles.VerticalSplitLineHeigth);
            rect.x += xOffset;
            EditorGUI.DrawRect(rect, LSEditorStyle.Line);
        }

        private bool ResearchLocalizationSetting()
        {
            string id = AssetDatabase.FindAssets(s_LocalizationSettingSearchFilter).FirstOrDefault();
            if (string.IsNullOrEmpty(id)) return false;
            try
            {
                string path = AssetDatabase.GUIDToAssetPath(id);
                var setting = AssetDatabase.LoadAssetAtPath<LocalizationSetting>(path);
                SetupLocalizationSettingEditor(setting);
                return true;
            }
            catch (System.Exception)
            {
                return false;
            }

        }

        private void CreateTableViewColumn(List<TableColumn> list)
        {
            list.AddRange(m_BasisColumn);
            for (int i = 0; i < m_TextKeys.Count; i++)
            {
                list.Add(new LanguageContentColumn(m_TextKeys[i]));
            }
        }

        private void SetupLocalizationSettingEditor(LocalizationSetting setting)
        {
            if (setting == m_Localization) return;
            m_Localization = setting;
            LoadLocalization(setting);
        }

        private void LoadLocalization(LocalizationSetting setting)
        {
            ClearAll();
            foreach (var item in setting.Collection)
            {
                AddLanguageSettingToViewToWindow(item.Setting);
            }
        }

        private void AddLanguageSettingToViewToWindow(LanguageSetting language)
        {
            LoadLanguageSetting(language);
        }

        private void RemoveLanguageSettingFromWindow(Language language)
        {
            string languageKey = language.ToString();
            m_ActivedLanguages.Remove(language);
            if (m_LanguageSettingTableItemMap.TryGetValue(language, out var tableItem))
            {
                m_LanguageSettingTableItemMap.Remove(language);
                m_LanguageSettingIdMap.Remove(tableItem.id);
                m_TableView.DeleteItem(tableItem);
            }

            if (m_LanguageAssetCollection.TryGetValue(language, out var list))
            {
                foreach (var item in list)
                {
                    m_XmlAssetTableItemMap.Remove(item);
                }
            }

            m_LanguageAssetCollection.Remove(language);
            
        }

        private void LoadLanguageSetting(LanguageSetting setting)
        {
            Language language = setting.Language;
            string languageKey = language.ToString();

            if (!m_ActivedLanguages.Contains(language))
                m_ActivedLanguages.Add(language);

            var tableItem = new LanguageSettingTableItem(language.GetHashCode(), 0, setting);
            m_LanguageSettingTableItemMap[setting.Language] = tableItem;
            m_LanguageSettingIdMap[tableItem.id] = tableItem;
            m_TableView?.AddItem(tableItem);
            foreach (TextAsset item in setting.Datas)
            {
                AddLanguageXMLToWindow(setting.Language, item);
            }
        }

        private void AddLanguageXMLToWindow(Language language, TextAsset asset)
        {
            if (m_LanguageAssetCollection.TryGetValue(language, out List<TextAsset> list))
            {
                if (!list.Contains(asset))
                    list.Add(asset);
            }
            else
            {
                list = new List<TextAsset>();
                list.Add(asset);
                m_LanguageAssetCollection[language] = list;
            }

            LoadTextAsset(language,asset);
        }

        private void RemoveLanguageXMLFromWindow(Language language, TextAsset asset)
        {
            if (m_LanguageAssetCollection.TryGetValue(language, out List<TextAsset> list))
            {
                list.Remove(asset);
            }
            var slItem = m_XmlAssetTableItemMap[asset];
            var parent = m_LanguageSettingTableItemMap[language];
            parent.children.Remove(slItem);
            if (m_XmlAssetTableItemMap.ContainsKey(asset))
            {
                m_XmlAssetTableItemMap.Remove(asset);
            }
        }

        private void LoadTextAsset(Language language, TextAsset asset)
        {
            var tableItem = new XMLTextFileTableItem(2, asset);
            m_XmlAssetTableItemMap[asset] = tableItem;
            var slItem = m_LanguageSettingTableItemMap[language];
            slItem.AddChild(tableItem);
            foreach (var item in tableItem.XmlCreater.Values)
            {
                if (!m_TextKeysSet.Contains(item.Key))
                {
                    m_TextKeysSet.Add(item.Key);
                    m_TextKeys.Add(item.Key);
                }
            }
        }

        private void ClearAll()
        {
            m_TextKeysSet?.Clear();
            m_TextKeys?.Clear();
            m_ActivedLanguages?.Clear();
            m_LanguageAssetCollection?.Clear();
            m_XmlAssetTableItemMap?.Clear();
            m_LanguageSettingIdMap?.Clear();
            m_LanguageSettingTableItemMap?.Clear();
            m_TableView?.ClearColump();
            m_TableView?.ClearItems();
            m_TableView?.AddColumn(this.m_BasisColumn);
        }

        public class LanguageSettingTableItem : TableViewItem<LanguageSetting>
        {

            public LanguageSettingTableItem(int id, int depth, LanguageSetting data) : base(id, depth, data, data.Language.ToString())
            {
            }

            public override void DrawItemGui(Rect rect, TableColumn column, bool isSelected, bool isFocused)
            {
                if (column.ColumnId == (int)ColumnType.Label)
                {
                    EditorGUI.LabelField(rect, this.displayName);
                }
                else if (column.ColumnId == (int)ColumnType.ObjectReference)
                {
                    EditorGUI.ObjectField(rect, this.Data, this.DataType, false);
                }
            }
        }

        public class XMLTextFileTableItem : TableViewItem<TextAsset>
        {
            private LanguageXMLCreater m_XmlCreater;
            public LanguageXMLCreater XmlCreater => m_XmlCreater;

            public XMLTextFileTableItem(int depth, TextAsset data) : base(data.GetHashCode(), depth, data, data.name)
            {
                m_XmlCreater = new LanguageXMLCreater(new LanguageXMLReader(data.text));
            }

            public override void DrawItemGui(Rect rect, TableColumn column, bool isSelected, bool isFocused)
            {
                if (column.ColumnId == (int)ColumnType.Label)
                {
                    EditorGUI.LabelField(rect, this.displayName);
                }
                else if (column.ColumnId == (int)ColumnType.ObjectReference)
                {
                    EditorGUI.ObjectField(rect, this.Data, this.DataType, false);
                }
                else if (column is LanguageContentColumn)
                {
                    LanguageContentColumn languageColumn = column as LanguageContentColumn;
                    string key = languageColumn.Key;
                    var contentValue = this.XmlCreater.GetContent(key);
                    if(contentValue != null)
                    {
                        Rect fixButtonRect = new Rect(rect.x + rect.width - 20, rect.y, 20, 20);
                        EditorGUI.LabelField(rect, contentValue.Value);
                        if (GUI.Button(fixButtonRect, "W"))
                        {
                            TextInputWindow.Show(UnityEngine.Event.current.mousePosition,
                                text =>
                                {
                                    if(text != contentValue.Value)
                                    {
                                        this.XmlCreater.AddContent(key, text);
                                    }
                                });
                        }
                    }
                }
            }

        }

        public enum ColumnType
        {
            Label = 1,
            ObjectReference = 2
        }

        public class LabelColumn : TableColumn
        {
            private int m_ColumnId = 1;

            public override int ColumnId => m_ColumnId;

            public LabelColumn() : base()
            {

                headerContent = new GUIContent("Label");
                width = 200;
                canSort = false;
                DrawCell = DrawColumnItem;
            }

            private void DrawColumnItem(Rect cellRect, TableViewItem data, int rowIndex, bool isSelected, bool isFocused)
            {
                data.DrawItemGui(cellRect, this, isSelected, isFocused);
            }
        }

        public class ObjectReferenceColumn : TableColumn
        {
            private int m_ColumnId = 2;
            public override int ColumnId => m_ColumnId;

            public ObjectReferenceColumn()
            {
                headerContent = new GUIContent("Object Reference");
                width = 150;
                canSort = false;
                DrawCell = DrawColumnItem;
            }

            private void DrawColumnItem(Rect cellRect, TableViewItem data, int rowIndex, bool isSelected, bool isFocused)
            {
                data.DrawItemGui(cellRect, this, isSelected, isFocused);
            }
        }

        public class LanguageContentColumn : TableColumn
        {
            private string m_Key;
            public override int ColumnId => m_Key.GetHashCode();

            public string Key => m_Key;

            public LanguageContentColumn(string languageKey)
            {
                m_Key = languageKey;
                headerContent = new GUIContent($"Key: {languageKey}");
                width = 150;
                canSort = false;
                DrawCell = DrawColumnItem;
            }

            private void DrawColumnItem(Rect cellRect, TableViewItem data, int rowIndex, bool isSelected, bool isFocused)
            {
                data.DrawItemGui(cellRect, this, isSelected, isFocused);
            }
        }
    }
}
